
package models;


import java.util.Random;

import tools.HasInvariant;
import abstractions.HangmanAbstraction;
import abstractions.HangmanSpecification;


/**
 * Version 3 of the hangman game implementation - where there is a good (?) OO design
 */
public class Hangman3 extends HangmanAbstraction implements HasInvariant, HangmanSpecification{
	
	private WordStore words;
	
	public boolean invariant(){
		if (!words.hasWord(currentWord)) return false;
		return super.invariant();
	}
	
	public Hangman3 (String word) throws IllegalArgumentException{
		
		String [] oneword = {word};
		
		if (word==null) throw new IllegalArgumentException("Cannot make a hangman game with no words");
		words = new WordStore(new Random(), oneword);
		randomWord();
}
	
	public Hangman3 (String []  strings) throws IllegalArgumentException{
		
		if (strings==null) throw new IllegalArgumentException("Cannot make a hangman game with no words");
		words = new WordStore(new Random(), strings);
		randomWord();
}
	
	public Hangman3 ( Random rng, String []  strings) throws IllegalArgumentException{
			
			if (strings==null) throw new IllegalArgumentException("Cannot make a hangman game with no words");
			words = new WordStore(rng, strings);
			randomWord();
	}
	
	public String getCurrentWord(){
		return currentWord;
	}
	
	public boolean foundWord(){
		
		for (int i=0; i<currentWord.length(); i++)
			if (!lettersFound[i]) return false;
		return true;
	}
	
	public int triesLeft(){ return ERROR_MAX - errorCount;}
	
	public boolean gameOver(){
		return foundWord() || triesLeft()<=0;
	}
	
	public void randomWord(){ 
		currentWord = words.randomWord();
		errorCount =0;
		won = false;
		lost = false;
		
		lettersFound = new boolean[currentWord.length()];
		for (int i=0; i<currentWord.length(); i++){
			lettersFound[i]=false;
		}
		
		for (int i=0; i<ALPHABET_SIZE; i++){
			lettersTried[i]=false;
		}
	}
	
	public String toString (){
		
		String str ="\nHangman -- Errors: "+errorCount+" from "+ERROR_MAX;
		str = str+"\nCurrent Word: "+currentWord;
		str = str+"\nLetters Found: "+ lettersInWord();	
		str = str+"\nLetters Tried: "+ lettersTried();
		str = str+"\nWon game is "+ won;
		str = str+"\nLost game is "+ lost;
		return str;
	}
	

    public String lettersTried(){
    String str="";
    	for (int i=0; i<ALPHABET_SIZE; i++)
    
		if (lettersTried[i]) str = str+ ((char) ( (int)('a') + i));
		else str =str+"-";
    	
    	return str;
    }
	public String lettersInWord(){
		
		String str="";
		
		for (int i=0; i<currentWord.length(); i++){
			if (lettersFound[i]) str = str+currentWord.charAt(i);
			else str=str+'?';
		}
		return str;
		
	}
	
	
	public void tryLetter(char letter) throws IllegalStateException, IllegalArgumentException{
		
	
		if (won) throw new IllegalStateException("Game is over: you already found the word");
		if (lost) throw new IllegalStateException("Game is over: no more attempts left");
		if (letter<ALPHABET_FROM || letter >ALPHABET_TO) 
			throw new IllegalArgumentException("Letters must be in alphabet");
		boolean found = false;
		int index = letter - (int)(ALPHABET_FROM);

		if (lettersTried[index]) return;
		
		else{	lettersTried[index] = true;
		        for (int i=0; i<currentWord.length(); i++)
			         if (currentWord.charAt(i)==letter){
			             lettersFound[i] = true;
			             found = true;}
		        if (!found){ errorCount++; 
		                     if (errorCount>ERROR_MAX) lost =true;
		                   }
			              
		    }
		won = foundWord();
		lost = (triesLeft()<1);
		}

}


